Video Downloads API
How to start, observe, and consume video downloads provided by DivaIOS.
Quick start​
- Create or adapt a model that conforms to
DownloadableItem(useDownloadItemSummaryfor simple cases). - Kick off a download with
try await DownloadManager.shared.startDownload(item:). - Observe progress and completions through
DownloadManager.shared.events(Combine).
import DivaIOS
let item = DownloadItemSummary(
id: "my-video-001",
title: "Episode 1",
path: "https://example.com/path/to/master.m3u8",
images: ["poster": URL(string: "https://example.com/poster.jpg")!]
)
Task {
try await DownloadManager.shared.startDownload(item: item)
}
Core types​
DownloadableItem: id, title,path(HLS or MP4 URL), optionalimages. Providesserialize()/deserialize()for persistence.DownloadItemSummaryis a ready-to-use implementation.DownloadManager(DownloadManagerType): main entry point. ExposesstartDownload,pauseDownload,resumeDownload,cancelDownload,getDownloadURL,isItemDownloaded,itemState,getItems(forStates:), plus bulk helpers (pauseAll,cancelAll,deleteAll,restart,cleanUp).DownloadState: lifecycle (initialized,requested,pending,downloading,paused,completed,error, etc.). UseDownloadState.isQueued/inProgressto drive UI.DownloadStateObserving: Combine publishers onDownloadManager(startedDownloadsPublisher,progressUpdatesPublisher,completedDownloadsPublisher,erroredDownloadsPublisher,stateChangesPublisher, unifiedevents).DownloadPolicy: controls account/profile scoping and URL shaping. Default is per-account (DownloadPolicyPerAccount); provide your own policy when you construct a customDownloadManager.
Observe download lifecycle (Combine)​
final class DownloadsViewModel: ObservableObject {
@Published var rows: [Row] = []
private var cancellables = Set<AnyCancellable>()
init(service: DownloadManager = .shared) {
service.events
.receive(on: DispatchQueue.main)
.sink { [weak self] event in
guard let self else { return }
switch event {
case .started(let e), .progress(let e), .stateChanged(let e), .completed(let e):
self.upsert(e)
case .failed(let e, let error):
self.markFailed(e, reason: error.localizedDescription)
}
}
.store(in: &cancellables)
}
}
Starting downloads​
- Direct URL: build a
DownloadItemSummarywith the stream URL inpathand callstartDownload(item:). - BO adapter convenience: if you already have an
SWTestCaseCleanModel(as used in the test app), callstartDownload(from:)to resolve entitlement and kick off the download. - Duplicate protection:
startDownloadthrowsDownloadError.alreadyQueuedwhen the same item is already in the queue;DownloadError.setupInProgressguards concurrent setup for the same id.
Managing the queue​
- Per-item:
pauseDownload(itemId:),resumeDownload(itemId:),cancelDownload(itemId:). - Bulk:
pauseAll(),cancelAll(),deleteAll()(completed/error/deleted/cancelling by default),restart()(rebuilds queued tasks after app relaunch),cleanUp()(removes orphaned records/files). - Queries:
getItems(forStates:)returns current entities filtered byDownloadState.
Accessing the downloaded file​
- Call
await getDownloadURL(itemId:)to obtain the local URL onceDownloadState.completed. await isItemDownloaded(itemId:)is a convenience boolean check.- Files persist under
Application Support/Downloads(seeDownloadDataManager.baseURL); HLS temporary.movpkgpaths are handled internally and returned as absolute URLs.
Background downloads​
- Downloads run in a background
URLSession. Bridge the system callback to the manager so the SDK can finish events:
// AppDelegate
func application(_ application: UIApplication,
handleEventsForBackgroundURLSession identifier: String,
completionHandler: @escaping () -> Void) {
DownloadManager.shared.backgroundCompletionHandler = completionHandler
}
- The provider notifies
DownloadManager.shared.completeBackgroundEventsIfNeeded()whenurlSessionDidFinishEventsfires; you only need to supply the completion handler above.
Policies, storage and limits​
- Policy: pass a custom
DownloadPolicywhen initializing your ownDownloadManagerif downloads should be scoped by profile/account rules - Capacity/cellular prompts:
DownloadManager.capacityWarningRequestsandcellularWarningRequestsare publishers you can use to present UI before proceeding when storage is tight or the connection switches to cellular.